﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;
using System.IO;

namespace PMCSerialTransfer
{
    public partial class frmPMC : Form
    {
        SerialPortManager _spManager;
        CommFactory _factory;
        SerialSettings mySerialSettings;
        public frmPMC()
        {
           InitializeComponent();
           mySerialSettings = new SerialSettings();
           mySerialSettings.GetSettings();
           _spManager = new SerialPortManager(mySerialSettings);
           _spManager.NewSerialDataReceived += new EventHandler<SerialDataEventArgs>(_spManager_NewSerialDataReceived);
           _factory = new CommFactory();
           this.FormClosing += new FormClosingEventHandler(MainForm_FormClosing);
          
           richTextBox1.TabStop = false;
           richTextBox1.ReadOnly = true;
           richTextBox1.BackColor = Color.White;
           richTextBox1.Cursor = Cursors.Arrow;
           richTextBox1.Enter += richTextBox_Enter;
           Globals.FileIndex = -1;
           //Crc16 crc = new Crc16();
           //richTextBox1.Text = "CRC Test: " + crc.Test();
        }

        private void richTextBox_Enter(object sender, EventArgs e)
        {
            // you need to set the focus somewhere else. Eg a label.
            menuStrip1.Focus();
        }

        private void configToolStripMenuItem_Click(object sender, EventArgs e)
        {
            frmConfig form;

            form = new frmConfig();
            mySerialSettings = _spManager.CurrentSerialSettings;
            mySerialSettings.GetSettings();
            form.InitializeValues(mySerialSettings);
            form.ShowDialog();
            mySerialSettings = form.Configure;
            richTextBox1.AppendText(form.Message);
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            _spManager.StartListening();
            if (Globals.Message != "")
                richTextBox1.AppendText(Globals.Message + "\n");
            else
                richTextBox1.AppendText(mySerialSettings.PortName + " opened\n");
           
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            _spManager.StopListening();
            richTextBox1.AppendText(mySerialSettings.PortName + " closed\n");
           
        }

        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;

            richTextBox1.AppendText(sp.ReadExisting());
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            _spManager.Dispose();
        }

        void _spManager_NewSerialDataReceived(object sender, SerialDataEventArgs e)
        {
            //byte[] dataPacket = new byte[2];

            if (this.InvokeRequired)
            {
                // Using this.Invoke causes deadlock when closing serial port, and BeginInvoke is good practice anyway.
                this.BeginInvoke(new EventHandler<SerialDataEventArgs>(_spManager_NewSerialDataReceived), new object[] { sender, e });
                return;
            }

            // This application is connected to a GPS sending ASCCI characters, so data is converted to text
            _factory.Factory(e.Data);
            richTextBox1.AppendText(Globals.Message);
            richTextBox1.SelectionStart=richTextBox1.Text.Length;
            richTextBox1.ScrollToCaret();
            switch (Globals.ProgressEvent)
            {
                case Globals.ProgressType.Load:
                    progressBar1.Maximum = Globals.FileLen;
                    progressBar1.Minimum = 0;
                    progressBar1.Value = 0;
                    break;
                case Globals.ProgressType.Add:
                    progressBar1.Value += (int)Globals.PacketSize;
                    break;
                case Globals.ProgressType.Clear:
                    progressBar1.Value = 0;
                    break;
                case Globals.ProgressType.None:
                    break;
            }
            //Globals.DataPacket[1] = (byte)CommFactory.Command.SndACK;
            //_factory.Factory(Globals.DataPacket);
            //Globals.DataPacket = _factory.Packet;
            _spManager.WriteData(Globals.DataPacket);
          

        }

        private void btnClear_Click(object sender, EventArgs e)
        {
            richTextBox1.Clear();
        }

        private void btnReset_Click(object sender, EventArgs e)
        {   
            _spManager.Reset();
            richTextBox1.AppendText("Propeller Reset\n" + mySerialSettings.PortName + " open\n");
            
        }

        private void btnRcvFile_Click(object sender, EventArgs e)
        {
            ReceiveFile();
        }

        private void ReceiveFile()
        {
            DialogResult rslt;
            string path;
            string file;
            Encoding utf8 = Encoding.UTF8;
            byte[] len = new byte[4];

            SerialSettings settings = new SerialSettings();
            settings.GetSettings();
            saveFileDialog1.InitialDirectory = settings.DefaultFolder;
            saveFileDialog1.Title = "Save File to PC";
            rslt = saveFileDialog1.ShowDialog();
            if (rslt == System.Windows.Forms.DialogResult.OK)
            {
                path = saveFileDialog1.FileName;
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
                Globals.FileStream = new FileStream(path, FileMode.CreateNew, FileAccess.Write);
                file = Path.GetFileName(path);
                Globals.DataPacket = new byte[file.Length];
                byte[] filebyte = utf8.GetBytes(file);
                for (int i = 0; i < filebyte.Length; i++)
                {
                    Globals.DataPacket[i] = filebyte[i];
                }
                //for (int i = 0; i < filebyte.Length; i++)
                //{
                //    Globals.DataPacket[i + 2] = filebyte[i];
                //}
                Globals.Create((byte)CommFactory.Command.SndFileName, Globals.DataPacket);
                richTextBox1.AppendText("Receiving " + file);

                _spManager.StartListening();
                _spManager.WriteData(Globals.DataPacket);
            }
        }


        private void ReceiveRam()
        {
            DialogResult rslt;
            string path;
            string file;
            Encoding utf8 = Encoding.UTF8;
            byte[] len = new byte[4];
            frmMemory mem;
            Int32 addr;
   

            SerialSettings settings = new SerialSettings();
            mem = new frmMemory();
            settings.GetSettings();
            saveFileDialog1.InitialDirectory = settings.DefaultFolder;
            saveFileDialog1.Title = "Save File to PC";
            rslt = saveFileDialog1.ShowDialog();
            if (rslt == System.Windows.Forms.DialogResult.OK)
            {
                path = saveFileDialog1.FileName;
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
                Globals.FileStream = new FileStream(path, FileMode.CreateNew, FileAccess.Write);
                mem.Receiving = true;
                rslt = mem.ShowDialog();
                if (rslt == System.Windows.Forms.DialogResult.OK)
                {
                    file = Path.GetFileName(path);
                    addr = mem.Address;
                    Globals.FileLen = mem.Length;
                    Globals.DataPacket = new byte[file.Length+8];
                    len = new byte[4];
                    len = BitConverter.GetBytes(Globals.FileLen);
                    for (int i = 0; i < 4; i++)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Globals.DataPacket[i] = len[3 - i];
                        }
                        else
                        {
                            Globals.DataPacket[i] = len[i];
                        }
                    }
                    byte[] addrlen = new byte[4];
                    addrlen = BitConverter.GetBytes(addr);
                    for (int i = 0; i < 4; i++)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Globals.DataPacket[i + 4] = addrlen[3 - i];
                        }
                        else
                        {
                            Globals.DataPacket[i + 4] = addrlen[i];
                        }
                    }

                    byte[] filebyte = utf8.GetBytes(file);
                    for (int i = 0; i < filebyte.Length; i++)
                    {
                        Globals.DataPacket[i+8] = filebyte[i];
                    }
                    //for (int i = 0; i < filebyte.Length; i++)
                    //{
                    //    Globals.DataPacket[i + 2] = filebyte[i];
                    //}
                    if (mem.isRam)
                        Globals.Create((byte)CommFactory.Command.RecvRAM, Globals.DataPacket);
                    else
                        Globals.Create((byte)CommFactory.Command.RecvEEPROM, Globals.DataPacket); 
                    richTextBox1.AppendText("Receiving " + file + " Bytes: " + Globals.FileLen.ToString() + " Addr: " + addr.ToString() + "\n");

                    _spManager.StartListening();
                    _spManager.WriteData(Globals.DataPacket);
                }
                else
                    Globals.Message = "Receive Memory Cancelled\n";
            }
        }
        private void btnSndFile_Click(object sender, EventArgs e)
        {
            SendFile();  
        }

        private void SendFile()
        {
            SerialSettings settings;
            DialogResult rslt;
            string fileName;
            Encoding utf8 = Encoding.UTF8;

            settings = new SerialSettings();
            settings.GetSettings();
            openFileDialog1.InitialDirectory = settings.DefaultFolder;
            openFileDialog1.CheckFileExists = true;
            rslt = openFileDialog1.ShowDialog();
            if (rslt == System.Windows.Forms.DialogResult.OK)
            {
                FileInfo fi = new FileInfo(openFileDialog1.FileName);
                fileName = fi.Name;
                //byte[] buff = new byte[fileName.Length + 6];
                Globals.DataPacket = new byte[fileName.Length + 4];
                Globals.FileLen = (int)fi.Length;
                byte[] len = new byte[4];
                len = BitConverter.GetBytes(Globals.FileLen);
                for (int i = 0; i < 4; i++)
                {
                    if (BitConverter.IsLittleEndian)
                    {
                        Globals.DataPacket[i] = len[3 - i];
                    }
                    else
                    {
                        Globals.DataPacket[i] = len[i];
                    }
                }
                byte[] filebyte = utf8.GetBytes(fileName);
                for (int i = 0; i < filebyte.Length; i++)
                {
                    Globals.DataPacket[i + 4] = filebyte[i];
                }
                Globals.Create((byte)CommFactory.Command.SndFileInfo, Globals.DataPacket);
                progressBar1.Maximum = (int)Globals.FileLen;
                progressBar1.Minimum = 0;
                progressBar1.Value = 0;
                Globals.FileStream = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read);
                richTextBox1.AppendText("Sending " + fi.Name + " Bytes: " + Globals.FileLen.ToString() + "\n");
                _spManager.StartListening();
                _spManager.WriteData(Globals.DataPacket);

            }
            else
            {
                Globals.Message = "File Send Cancelled";
            }
        }

        private void SendMem()
        {
            SerialSettings settings;
            DialogResult rslt;
            string fileName;
            Encoding utf8 = Encoding.UTF8;
            frmMemory mem;
            Int32 addr;
            bool isRam;
            string memstr;

            settings = new SerialSettings();
            mem = new frmMemory();
            settings.GetSettings();
            openFileDialog1.InitialDirectory = settings.DefaultFolder;
            openFileDialog1.CheckFileExists = true;
            rslt = openFileDialog1.ShowDialog();
            if (rslt == System.Windows.Forms.DialogResult.OK)
            {
                rslt = mem.ShowDialog();
                if (rslt == System.Windows.Forms.DialogResult.OK)
                {
                    addr = mem.Address;
                    isRam = mem.isRam;
                    mem.Receiving = false;
                    FileInfo fi = new FileInfo(openFileDialog1.FileName);
                    fileName = fi.Name;
                    //byte[] buff = new byte[fileName.Length + 6];
                    Globals.DataPacket = new byte[fileName.Length + 8];
                    Globals.FileLen = (int)fi.Length;
                    byte[] len = new byte[4];
                    len = BitConverter.GetBytes(Globals.FileLen);
                    for (int i = 0; i < 4; i++)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Globals.DataPacket[i] = len[3 - i];
                        }
                        else
                        {
                            Globals.DataPacket[i] = len[i];
                        }
                    }
                    byte[] addrlen = new byte[4];
                    addrlen = BitConverter.GetBytes(addr);
                    for (int i = 0; i < 4; i++)
                    {
                        if (BitConverter.IsLittleEndian)
                        {
                            Globals.DataPacket[i+4] = addrlen[3 - i];
                        }
                        else
                        {
                            Globals.DataPacket[i+4] = addrlen[i];
                        }
                    }
                    byte[] filebyte = utf8.GetBytes(fileName);
                    for (int i = 0; i < filebyte.Length; i++)
                    {
                        Globals.DataPacket[i + 8] = filebyte[i];
                    }
                    if (isRam)
                    {
                        Globals.Create((byte)CommFactory.Command.SndRAM, Globals.DataPacket);
                        memstr = " RAM\n";
                    }
                    else
                    {
                        Globals.Create((byte)CommFactory.Command.SendEEPROM, Globals.DataPacket);
                        memstr = " EEPROM\n";
                    }
                    progressBar1.Maximum = (int)Globals.FileLen;
                    progressBar1.Minimum = 0;
                    progressBar1.Value = 0;
                    Globals.FileStream = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read);
                    richTextBox1.AppendText("Sending " + fi.Name + memstr + "  Bytes: " + Globals.FileLen.ToString() + " Addr: "+ addr + "\n");
                    _spManager.StartListening();
                    _spManager.WriteData(Globals.DataPacket);
                }
                else
                {
                    Globals.Message = "Memory Send Cancelled";
                }
            }
        }

        private void btnSndMemory_Click(object sender, EventArgs e)
        {
            SendMem();
        }

        private void btnRcvList_Click(object sender, EventArgs e)
        {
            ReceiveList();
        }

        private void ReceiveList()
        {
            Globals.DataPacket = new byte[0];
            Globals.Create((byte)CommFactory.Command.RecvList, Globals.DataPacket);
            _spManager.StartListening();
            _spManager.WriteData(Globals.DataPacket);
        }

        private void btnSndList_Click(object sender, EventArgs e)
        {
            SendList();
        }

        private void SendList()
        {
            Globals.DataPacket = new byte[0];
            Globals.Create((byte)CommFactory.Command.SendList, Globals.DataPacket);
            //byte[] buff = new byte[2];
            //buff[0] = 6;
            //buff[1] = (byte)CommFactory.Command.SendList;
            //UInt32 crc = Crc32.Compute(buff);
            //byte[] len = BitConverter.GetBytes(crc);
            //Globals.DataPacket = new byte[buff.Length + 4];

            //for (int i = 0; i < buff.Length; i++)
            //{
            //    Globals.DataPacket[i] = buff[i];
            //}
            //for (int i = 0; i < 4; i++)
            //{
            //    if (BitConverter.IsLittleEndian)
            //    {
            //        Globals.DataPacket[i + buff.Length] = len[3 - i];
            //    }
            //    else
            //    {
            //        Globals.DataPacket[i + buff.Length] = len[i];
            //    }
            //}
            _spManager.StartListening();
            _spManager.WriteData(Globals.DataPacket);
        }

        private void sendFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SendFile();
        }

        private void recieveFileToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ReceiveFile();
        }

        private void sendListingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SendList();
        }

        private void receiveListingToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ReceiveList();
        }

        private void btnRam_Click(object sender, EventArgs e)
        {
            Propellent propNet;
            bool isOpen;

            isOpen = _spManager.IsOpen();
            if (isOpen)
                _spManager.StopListening();
            mySerialSettings.GetSettings();
            propNet = new Propellent(this.Handle, false, null);
            propNet.DownloadToPropeller(mySerialSettings.BinaryFile, Propellent.LoadType.RAM);
            if (isOpen)
                _spManager.StartListening();
        }

        private void btnEEPROM_Click(object sender, EventArgs e)
        {
            Propellent propNet;
            bool isOpen;

            isOpen = _spManager.IsOpen();
            if (isOpen)
                _spManager.StopListening();

            mySerialSettings.GetSettings();
            propNet = new Propellent(this.Handle, false, null);
            propNet.DownloadToPropeller(mySerialSettings.BinaryFile, Propellent.LoadType.EEPROM_RUN);
            if (isOpen)
                _spManager.StartListening();
        }

        private void btnRCVMemory_Click(object sender, EventArgs e)
        {
            ReceiveRam();
        }

        private void btnUnmount_Click(object sender, EventArgs e)
        {
            Globals.DataPacket = new byte[1];
            Globals.DataPacket[0] = (byte)Globals.ACKType.E_ACK;
            Globals.Create((byte)CommFactory.Command.Unmount, Globals.DataPacket);
            richTextBox1.AppendText("Unmounting SD Card\n");
            _spManager.StartListening();
            _spManager.WriteData(Globals.DataPacket);
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
           
        }

        private void versionToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 about;

            about = new AboutBox1();
            about.Show();
        }

        private void helpToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string path = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\PACS.chm";
            System.Diagnostics.Process.Start(path);
        }

    }
};